
#include "Thread.h"

#include <iostream>
#include <stdexcept>
#include <sys/syscall.h>
#include <unistd.h>

namespace zepco {
static thread_local Thread *t_thread = nullptr;
static thread_local std::string t_thread_name = "UNKOWN";

pid_t Thread::GetThreadID() {
    return syscall(SYS_gettid);
}

Thread *Thread::GetThis() {
    return t_thread;
}

const std::string &Thread::GetThreadName() {
    return t_thread_name;
}

void Thread::SetName(std::string &name) {
    if (t_thread) {
        t_thread->m_name = name;
    }
    t_thread_name = name;
}

Thread::Thread(std::function<void()> callback, const std::string &name)
    : m_callback(callback), m_name(name) {
    int ret = pthread_create(&m_thread, nullptr, &Thread::run, this);
    if (ret) {
        std::cerr << "pthread_create thread fail. ret = " << ret << std::endl;
        throw std::logic_error("pthread_create error");
    }
    m_semaphore.wait();
}

Thread::~Thread() {
    if (m_thread) {
        pthread_detach(m_thread);
        m_thread = 0;
    }
}

void Thread::join() {
    if (m_thread) {
        int ret = pthread_join(m_thread, nullptr);
        if (ret) {
            std::cerr << "pthread_join fail, ret = " << ret << ", name = " << m_name << std::endl;
            throw std::logic_error("pthread_join error");
        }
        m_thread = 0;
    }
}

void *Thread::run(void *arg) {
    Thread *thread = (Thread *)arg;
    t_thread = thread;
    t_thread_name = thread->m_name;
    thread->m_id = GetThreadID();
    pthread_setname_np(pthread_self(), thread->m_name.substr(0, 15).c_str());
    std::function<void()> cb;
    cb.swap(thread->m_callback);
    thread->m_semaphore.singal(); // ??
    cb();
    return nullptr;
}

}